package com.ruoyi.controller;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.vo.DeptUserDto;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.service.SysDeptServiceImpl;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 部门信息
 */
@RestController
@RequestMapping("/system/dept")
public class SysDeptController extends BaseController {
    @Autowired
    private SysDeptServiceImpl deptService;

    /**
     * 获取部门列表
     */

    @GetMapping("/list")
    public AjaxResult list(SysDept dept) {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return success(depts);
    }

    /**
     * 查询部门列表（排除节点）
     */

    @GetMapping("/list/exclude/{deptId}")
    public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
        return success(depts);
    }

    /**
     * 根据部门编号获取详细信息
     */

    @GetMapping(value = "/{deptId}")
    public AjaxResult getInfo(@PathVariable Long deptId) {
        deptService.checkDeptDataScope(deptId);
        return success(deptService.selectDeptById(deptId));
    }

    /**
     * 新增部门
     */


    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDept dept) {
        if (!deptService.checkDeptNameUnique(dept)) {
            return error("新增部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        }
        dept.setCreateBy(getUsername());
        return toAjax(deptService.insertDept(dept));
    }

    /**
     * 修改部门
     */


    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDept dept) {
        Long deptId = dept.getDeptId();
        deptService.checkDeptDataScope(deptId);
        if (!deptService.checkDeptNameUnique(dept)) {
            return error("修改部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        } else if (dept.getParentId().equals(deptId)) {
            return error("修改部门'" + dept.getDeptName() + "'失败，上级部门不能是自己");
        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) {
            return error("该部门包含未停用的子部门！");
        }
        dept.setUpdateBy(getUsername());
        return toAjax(deptService.updateDept(dept));
    }

    /**
     * 删除部门
     */


    @DeleteMapping("/{deptId}")
    public AjaxResult remove(@PathVariable Long deptId) {
        deptService.deleteDeptById(deptId);
        return success();
    }


    /**
     * 获取部门以及员工Tree
     */
    @GetMapping(value = "/getDeptUserTree")
    public AjaxResult getDeptUserTree() throws IOException, ClassNotFoundException {
        //SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        List<DeptUserDto> depts = deptService.getDeptUserTree();
        List<DeptUserDto> deptPostAll = deptService.getDeptPost();

        List<DeptUserDto> deptPosts = new ArrayList<>();
        List<DeptUserDto> posts = deptService.getPostList();
        for (int i = 0; i < depts.size(); i++) {
            if (depts.get(i).getType().equals("部门")) {
                deptPosts.addAll(getRootPost(depts.get(i), posts, deptPostAll));
            }
        }
        depts.addAll(deptPosts);

        BiFunction<DeptUserDto, List<DeptUserDto>, DeptUserDto> setChild = DeptUserDto::setChild;
        Function<DeptUserDto, Boolean> isRoot = DeptUserDto::isRoot;
        BiFunction<DeptUserDto, List<DeptUserDto>, List<DeptUserDto>> getChild = (e, list) -> list.stream().filter(a -> Objects.equals(a.getParentId(), e.getId())).collect(Collectors.toList());
        List<DeptUserDto> deptUserList = StringUtils.toTree(depts, setChild, getChild, isRoot);

        String s = JSON.toJSONString(deptUserList);
        s = s.replaceAll("\"children\":\\[],", "");

        AjaxResult ajax = AjaxResult.success();
        ajax.put("depts", s);
        return ajax;
    }


    private List<DeptUserDto> getRootPost(DeptUserDto dept, List<DeptUserDto> posts, List<DeptUserDto> deptPostAll) throws IOException, ClassNotFoundException {
        List<DeptUserDto> childs = BeanUtils.copyList(posts);
        List<String> deptPost = deptPostAll.stream().filter(r -> r.getAncestors().contains("," + dept.getDeptId() + ",")).map(DeptUserDto::getPostId).collect(Collectors.toList());
        childs = childs.stream().filter(c -> deptPost.contains(c.getPostId())).collect(Collectors.toList());
        if (childs.size() == 0) {
            return new ArrayList<>();
        }
        DeptUserDto rootPost = new DeptUserDto();
        rootPost.setChild(childs);
        rootPost.setType("岗位");
        rootPost.setLabel("岗位");
        rootPost.setParentId(dept.getDeptId());
        rootPost.setId("岗位root|" + dept.getDeptId());
        childs.forEach(row -> {
            row.setParentId(rootPost.getDeptId());
            row.setId(row.getId() + "|" + dept.getDeptId());
        });
        childs.add(rootPost);
        return childs;
    }

    /**
     * 部门管理列表
     */
    @RequestMapping(value = "/getList")
    public Object getList(@RequestParam Map<String, Object> param) {
        return success(deptService.departmentManagementGetList(param));
    }

    /**
     * 选择部门树下拉框
     */
    @RequestMapping(value = "/deptTreeSelect", name = "选择部门树下拉框,有权限")
    public Object deptTreeSelect() {
        return success(deptService.departmentManagementGetList(new HashMap<>()));
    }

    /**
     * 部门管理列表
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/doEdit", name = "部门编辑、专业组保存")
    public Object doEdit(SysDept dept) {
        if (dept.getDeptId() != null) {
            deptService.updateDept(dept);
        } else {
            deptService.insertDept(dept);
        }
        return success();
    }

    @RequestMapping(value = "/doDelete")
    public Object doDelete(Long id) {
        deptService.deleteDeptById(id);
        return success();
    }

    @RequestMapping(value = "/updateUse", name = "部门停用启用")
    @Transactional(rollbackFor = Exception.class)
    public Object updateUse(Long deptId) {
        deptService.updateUse(deptId);
        return "";
    }
}
